# = StarFrame::Sprite::Animatable -- スプライトアニメーション
require "starframe/sprite/animation"

module StarFrame
  class Sprite
    # = Sprite::Animatableモジュール
    # スプライトアニメーションモジュール。
    # 
    # Spriteクラスのサブクラス定義内でincludeし、animateクラスメソッドでアニメーションを定義する。
    # 
    #   class AnimatedSprite < StarFrame::Sprite
    #     animate :rolling do |c|
    #       frames 0, 360.linear do
    #         self.anlge = c
    #       end
    #     end
    #   end
    module Animatable
      def self.included sprite #:nodoc:
        unless sprite.include? StarFrame::Eventable
          raise TypeError, "StarFrame::Sprite::Animatable : has need \"include StarFrame::Eventable\"", caller
        end
        
        sprite.extend ClassMethods
        sprite.module_eval do
          alias_method_chain :call_init,   :animation
          alias_method_chain :call_update, :animation
          
          @animations = Hash.new{ |hash, key| hash[key] = [] }
        end
      end
      
      def call_init_with_animation *args #:nodoc:
        @animations = {}
        self.class.animations.each do |name, animation|
          @animations[name] = animation.build(self)
        end
        
        call_init_without_animation *args
      end
      
      def call_update_with_animation #:nodoc:
        call_update_without_animation
        
        @animations.each do |name, animation|
          animation.update
        end
      end
      
      # アニメーションを取得
      def animation name
        @animations[name]
      end
      
      module ClassMethods
        attr_accessor :animations #:nodoc:
        
        # アニメーションを定義
        # 
        # StarFrame::Sprite::Animatable::Animation::Builderクラスのインスタンスを新規に作成し、Spriteに設定する。
        # 
        # params
        #   name - アニメーション名。アニメーション操作に使用する。
        #   options - オプションのHash
        #     :loop - ループするかどうか
        #   &block - アニメーション定義
        def animation name, options = {:loop => true}, &block
          animation = Animation::Builder.new(self, name, options, &block)
          @animations[name] = animation
        end
        
        def inherited klass #:nodoc:
          klass.animations = @animations.dup
          super
        end
      end
    end
  end
end
